package com.pai4j.pgc.service;

import com.pai4j.common.bean.PAIResponseBean;
import com.pai4j.common.constants.ResourceBehaviorConstants;
import com.pai4j.common.enums.ArticleStatusEnum;
import com.pai4j.common.enums.DeleteFlagCodeEnum;
import com.pai4j.common.enums.RedisKeyEnum;
import com.pai4j.common.enums.SubjectRelationStatusEnum;
import com.pai4j.common.util.JsonUtil;
import com.pai4j.common.util.RedisUtil;
import com.pai4j.domain.vo.request.request.act.ResourceBehaviorRequestVO;
import com.pai4j.domain.vo.response.subjectaccount.SubjectStatisticsVO;
import com.pai4j.domain.vo.response.subjectaccount.UserArticleStatisticsVO;
import com.pai4j.pgc.dao.IArticleDAO;
import com.pai4j.pgc.dao.ISubjectSubcribeDAO;
import com.pai4j.pgc.entity.ArticleEntity;
import com.pai4j.remote.act.IResourceBehaviorClient;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 文章统计服务
 * 提供用户文章统计和专题统计功能，并使用Redis缓存提高性能
 *
 * @author: CYM-pai
 * @date: 2025/10/09
 **/
@Slf4j
@Service
public class ArticleStatisticsService {

    @Resource
    private IArticleDAO articleDAO;

    @Resource
    private ISubjectSubcribeDAO subjectSubscribeDAO;

    @Resource
    private RedisUtil redisUtil;

    @Autowired(required = false)
    private IResourceBehaviorClient resourceBehaviorClient;

    /**
     * 获取用户文章统计信息（带缓存）
     * 统计指定作者的已发布文章数、草稿数等信息
     *
     * @param author 作者ID
     * @return 用户文章统计信息
     */
    public UserArticleStatisticsVO getUserArticleStatistics(String author) {
        if (StringUtils.isBlank(author)) {
            return null;
        }

        // 1. 尝试从缓存中获取
        String cacheKey = RedisKeyEnum.USER_ARTICLE_STATISTICS_CACHE.getKey(author);
        String cache = redisUtil.get(cacheKey);
        if (StringUtils.isNotBlank(cache)) {
            log.debug("从缓存获取用户文章统计: author={}", author);
            return JsonUtil.fromJson(cache, UserArticleStatisticsVO.class);
        }

        // 2. 缓存不存在，从数据库查询并构建统计数据
        log.debug("从数据库查询用户文章统计: author={}", author);
        UserArticleStatisticsVO statistics = buildUserArticleStatistics(author);

        // 3. 将统计结果缓存到Redis
        if (statistics != null) {
            redisUtil.set(cacheKey, JsonUtil.toJsonString(statistics), 
                    RedisKeyEnum.USER_ARTICLE_STATISTICS_CACHE.getExpireTime());
        }

        return statistics;
    }

    /**
     * 构建用户文章统计信息（区分未删除和已删除）
     *
     * @param author 作者ID
     * @return 用户文章统计信息
     */
    private UserArticleStatisticsVO buildUserArticleStatistics(String author) {
        Integer unDeleteFlag = DeleteFlagCodeEnum.UN_DELETE.getCode();
        Integer deleteFlag = DeleteFlagCodeEnum.DELETE.getCode();
        
        // 统计已发布文章数（状态为已推送，过滤已删除）
        Long publishedCount = articleDAO.countPublishedByAuthorAndDeleteFlag(
                author, 
                ArticleStatusEnum.PUSHED.getStatus(),
                unDeleteFlag);

        // 统计草稿数（状态为草稿，过滤已删除）
        Long draftCount = articleDAO.countByAuthorAndStatusAndDeleteFlag(
                author, 
                ArticleStatusEnum.DRAFT.getStatus(),
                unDeleteFlag);

        // 统计已删除文章数
        Long deletedCount = articleDAO.countByAuthorAndDeleteFlag(author, deleteFlag);

        // 统计文章总浏览数（从 act 模块获取，只统计未删除的文章）
        Long totalViewCount = calculateTotalViewCount(author);

        return UserArticleStatisticsVO.builder()
                .userId(author)
                .publishedArticleCount(publishedCount != null ? publishedCount : 0L)
                .draftArticleCount(draftCount != null ? draftCount : 0L)
                .deletedArticleCount(deletedCount != null ? deletedCount : 0L)
                .totalViewCount(totalViewCount)
                .statisticsTime(System.currentTimeMillis())
                .build();
    }

    /**
     * 计算用户所有文章的总浏览数（只统计未删除的文章）
     * 该方法会查询用户所有已发布且未删除的文章，并累加每篇文章的浏览数
     *
     * @param author 作者ID
     * @return 文章总浏览数
     */
    private Long calculateTotalViewCount(String author) {
        // 如果 act 服务客户端未注入（服务不可用），返回 0
        if (resourceBehaviorClient == null) {
            log.warn("IResourceBehaviorClient 未注入，无法统计文章浏览数");
            return 0L;
        }

        try {
            // 查询作者所有已发布且未删除的文章（分批查询以避免一次性加载过多数据）
            long totalViewCount = 0L;
            // 每次查询100篇文章
            int pageSize = 100;
            int pageNo = 0;
            boolean hasMore = true;

            while (hasMore) {
                Pageable pageable = PageRequest.of(pageNo, pageSize);
                // 只查询已发布且未删除的文章
                Page<ArticleEntity> articlePage = articleDAO.findByAuthorAndStatusAndDeleteFlag(
                        author, 
                        ArticleStatusEnum.PUSHED.getStatus(),
                        DeleteFlagCodeEnum.UN_DELETE.getCode(),
                        pageable);

                if (articlePage.hasContent()) {
                    List<ArticleEntity> articles = articlePage.getContent();
                    
                    // 批量统计每篇文章的浏览数
                    for (ArticleEntity article : articles) {
                        Long viewCount = getArticleViewCount(article.getId());
                        totalViewCount += (viewCount != null ? viewCount : 0L);
                    }

                    hasMore = articlePage.hasNext();
                    pageNo++;
                } else {
                    hasMore = false;
                }
            }

            return totalViewCount;
        } catch (Exception e) {
            log.error("计算文章总浏览数失败: author={}", author, e);
            return 0L;
        }
    }

    /**
     * 获取单篇文章的浏览数
     * 调用 act 模块的接口统计文章的浏览次数
     *
     * @param articleId 文章ID
     * @return 文章浏览数
     */
    private Long getArticleViewCount(Long articleId) {
        try {
            // 构建资源行为请求
            ResourceBehaviorRequestVO request = new ResourceBehaviorRequestVO();
            request.setResourceId(articleId);
            request.setResourceType(ResourceBehaviorConstants.ResourceType.ARTICLE.name());
            request.setBehaviorType(ResourceBehaviorConstants.BehaviorType.VIEW.name());
            // countBehavior 接口不需要 userId，但为了避免可能的参数校验问题，设置为 "system"
            request.setUserId("system");

            // 调用 act 服务统计浏览数
            PAIResponseBean<Long> response = resourceBehaviorClient.countBehavior(request);
            if (response != null && response.getData() != null) {
                return response.getData();
            }
        } catch (Exception e) {
            log.error("获取文章浏览数失败: articleId={}", articleId, e);
        }
        return 0L;
    }

    /**
     * 获取专题统计信息（带缓存）
     * 统计指定专题的订阅数、文章总数、已发布文章数等信息
     *
     * @param subjectId 专题ID
     * @return 专题统计信息
     */
    public SubjectStatisticsVO getSubjectStatistics(Long subjectId) {
        if (subjectId == null) {
            return null;
        }

        // 1. 尝试从缓存中获取
        String cacheKey = RedisKeyEnum.SUBJECT_STATISTICS_CACHE.getKey(String.valueOf(subjectId));
        String cache = redisUtil.get(cacheKey);
        if (StringUtils.isNotBlank(cache)) {
            log.debug("从缓存获取专题统计: subjectId={}", subjectId);
            return JsonUtil.fromJson(cache, SubjectStatisticsVO.class);
        }

        // 2. 缓存不存在，从数据库查询并构建统计数据
        log.debug("从数据库查询专题统计: subjectId={}", subjectId);
        SubjectStatisticsVO statistics = buildSubjectStatistics(subjectId);

        // 3. 将统计结果缓存到Redis
        if (statistics != null) {
            redisUtil.set(cacheKey, JsonUtil.toJsonString(statistics), 
                    RedisKeyEnum.SUBJECT_STATISTICS_CACHE.getExpireTime());
        }

        return statistics;
    }

    /**
     * 构建专题统计信息（过滤已删除的文章）
     *
     * @param subjectId 专题ID
     * @return 专题统计信息
     */
    private SubjectStatisticsVO buildSubjectStatistics(Long subjectId) {
        String subjectAccount = String.valueOf(subjectId);
        Integer unDeleteFlag = DeleteFlagCodeEnum.UN_DELETE.getCode();

        // 统计专题订阅数（状态为已订阅）
        Long subscriptionCount = subjectSubscribeDAO.countBySubjectIdAndStatus(
                subjectId, SubjectRelationStatusEnum.CONFIRMED.getStatus());

        // 统计专题文章总数（该专题下所有状态的未删除文章）
        Long totalArticleCount = articleDAO.countBySubjectAccountAndStatusAndDeleteFlag(
                subjectAccount, ArticleStatusEnum.PUSHED.getStatus(), unDeleteFlag);
        Long draftCount = articleDAO.countBySubjectAccountAndStatusAndDeleteFlag(
                subjectAccount, ArticleStatusEnum.DRAFT.getStatus(), unDeleteFlag);
        Long waitPushCount = articleDAO.countBySubjectAccountAndStatusAndDeleteFlag(
                subjectAccount, ArticleStatusEnum.WAIT_PUSH.getStatus(), unDeleteFlag);
        totalArticleCount = (totalArticleCount != null ? totalArticleCount : 0L) +
                (draftCount != null ? draftCount : 0L) +
                (waitPushCount != null ? waitPushCount : 0L);

        // 统计专题已发布文章数（状态为已推送，过滤已删除）
        Long publishedArticleCount = articleDAO.countPublishedBySubjectAndDeleteFlag(
                subjectAccount, 
                ArticleStatusEnum.PUSHED.getStatus(),
                unDeleteFlag);

        return SubjectStatisticsVO.builder()
                .subjectId(subjectId)
                .subscriptionCount(subscriptionCount != null ? subscriptionCount : 0L)
                .totalArticleCount(totalArticleCount)
                .publishedArticleCount(publishedArticleCount != null ? publishedArticleCount : 0L)
                .statisticsTime(System.currentTimeMillis())
                .build();
    }

    /**
     * 刷新用户文章统计缓存
     * 当用户发布或删除文章时调用此方法更新缓存
     *
     * @param author 作者ID
     */
    public void refreshUserArticleStatisticsCache(String author) {
        if (StringUtils.isBlank(author)) {
            return;
        }

        log.debug("刷新用户文章统计缓存: author={}", author);
        String cacheKey = RedisKeyEnum.USER_ARTICLE_STATISTICS_CACHE.getKey(author);
        
        // 重新构建统计数据
        UserArticleStatisticsVO statistics = buildUserArticleStatistics(author);
        
        // 更新缓存
        if (statistics != null) {
            redisUtil.set(cacheKey, JsonUtil.toJsonString(statistics), 
                    RedisKeyEnum.USER_ARTICLE_STATISTICS_CACHE.getExpireTime());
        }
    }

    /**
     * 刷新专题统计缓存
     * 当专题订阅数或文章数变化时调用此方法更新缓存
     *
     * @param subjectId 专题ID
     */
    public void refreshSubjectStatisticsCache(Long subjectId) {
        if (subjectId == null) {
            return;
        }

        log.debug("刷新专题统计缓存: subjectId={}", subjectId);
        String cacheKey = RedisKeyEnum.SUBJECT_STATISTICS_CACHE.getKey(String.valueOf(subjectId));
        
        // 重新构建统计数据
        SubjectStatisticsVO statistics = buildSubjectStatistics(subjectId);
        
        // 更新缓存
        if (statistics != null) {
            redisUtil.set(cacheKey, JsonUtil.toJsonString(statistics), 
                    RedisKeyEnum.SUBJECT_STATISTICS_CACHE.getExpireTime());
        }
    }

    /**
     * 删除用户文章统计缓存
     *
     * @param author 作者ID
     */
    public void deleteUserArticleStatisticsCache(String author) {
        if (StringUtils.isBlank(author)) {
            return;
        }

        String cacheKey = RedisKeyEnum.USER_ARTICLE_STATISTICS_CACHE.getKey(author);
        redisUtil.remove(cacheKey);
        log.debug("删除用户文章统计缓存: author={}", author);
    }

    /**
     * 删除专题统计缓存
     *
     * @param subjectId 专题ID
     */
    public void deleteSubjectStatisticsCache(Long subjectId) {
        if (subjectId == null) {
            return;
        }

        String cacheKey = RedisKeyEnum.SUBJECT_STATISTICS_CACHE.getKey(String.valueOf(subjectId));
        redisUtil.remove(cacheKey);
        log.debug("删除专题统计缓存: subjectId={}", subjectId);
    }
}

